package com.tianhua.amis4j.service.admin;

import com.coderman.model.meta.bean.back.ApiBean;
import com.coderman.model.meta.bean.back.CreateCodeConfigBean;
import com.coderman.model.meta.bean.back.ModuleBean;
import com.coderman.model.meta.bean.back.WebCodeBean;
import com.coderman.model.meta.bean.support.PageBean;
import com.coderman.model.meta.engine.WebCodeGenerator;
import com.tianhua.amis4j.infrast.dataobject.ModuleConfigDO;
import com.tianhua.amis4j.infrast.mapper.ModuleConfigMapper;
import com.tianhua.amis4j.service.utils.ZipUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Description:
 * date: 2022/4/19
 *
 * @author fanchunshuai
 * @version 1.0.0
 * @since JDK 1.8
 */
@Service
@Slf4j
public class ModuleConfigService {
    @Resource
    private ModuleConfigMapper moduleConfigMapper;


    @Autowired
    private ApiConfigService apiConfigService;


    @Autowired
    private WebCodeGenerator webCodeGenerator;


    @Autowired
    private WebCodeService webCodeService;

    public long saveModuleConfig(ModuleBean moduleBean){
        ModuleConfigDO moduleConfigDO = new ModuleConfigDO();
        BeanUtils.copyProperties(moduleBean,moduleConfigDO);
        return moduleConfigMapper.insert(moduleConfigDO);
    }

    public void updateModuleConfig(ModuleBean moduleBean){
        ModuleConfigDO moduleConfigDO = new ModuleConfigDO();
        BeanUtils.copyProperties(moduleBean,moduleConfigDO);
        moduleConfigMapper.update(moduleConfigDO);
    }


    public PageBean selectPage(PageBean pageBean){
        List<ModuleConfigDO> moduleConfigDOList = moduleConfigMapper.getPageList(pageBean);
        List<ModuleBean> moduleBeanList = new ArrayList<>();
        for (ModuleConfigDO moduleConfigDO : moduleConfigDOList){
            ModuleBean moduleBean = new ModuleBean();
            BeanUtils.copyProperties(moduleConfigDO,moduleBean);
            moduleBeanList.add(moduleBean);
        }
        pageBean.setCount(moduleConfigMapper.getPageCount(pageBean));
        pageBean.setRows(moduleBeanList);
        return pageBean;
    }

    public List<ModuleBean> getByProjectCode(String projectCode){
        List<ModuleConfigDO> moduleConfigDOList = moduleConfigMapper.getByProjectCode(projectCode);

        List<ModuleBean> moduleBeanList = new ArrayList<>();
        for (ModuleConfigDO moduleConfigDO : moduleConfigDOList){
            ModuleBean moduleBean = new ModuleBean();
            BeanUtils.copyProperties(moduleConfigDO,moduleBean);
            moduleBeanList.add(moduleBean);
        }

        return moduleBeanList;
    }

    public ModuleBean getById(Long id){
        ModuleConfigDO moduleConfigDO = moduleConfigMapper.getById(id);
        ModuleBean moduleBean = new ModuleBean();
        BeanUtils.copyProperties(moduleConfigDO,moduleBean);
        List<ApiBean> apiBeanList = apiConfigService.getByModuleCode(moduleBean.getModuleCode());
        moduleBean.setApiBeanList(apiBeanList);




        return moduleBean;
    }


    public List<ModuleBean> search(String content){
        List<ModuleConfigDO> moduleConfigDOList = moduleConfigMapper.getAll( content);
        List<ModuleBean> moduleBeanList = new ArrayList<>();
        for (ModuleConfigDO moduleConfigDO : moduleConfigDOList){
            ModuleBean moduleBean = new ModuleBean();
            BeanUtils.copyProperties(moduleConfigDO,moduleBean);
            moduleBeanList.add(moduleBean);
        }
        return moduleBeanList;
    }


    public void createWebCode(CreateCodeConfigBean createCodeConfigBean){
        webCodeGenerator.createWebCode(createCodeConfigBean);
    }


    /**
     * 构建代码zip包
     * @param moduleId
     * @return
     */
    public String downloadCode(Long moduleId){
        ModuleBean moduleBean = this.getById(moduleId);
        List<WebCodeBean> webCodeList = webCodeService.selectByProjectCode(moduleBean.getProjectCode());
        List<WebCodeBean> webCodeBeanList = webCodeList.stream().filter(webCodeBean -> webCodeBean.getModuleCode().equals(moduleBean.getModuleCode())).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(webCodeBeanList)){
            log.warn("该模块还没有构建代码,请先去构建代码!");
            return "该模块还没有构建代码,请先去构建代码!";
        }

        Map<String,WebCodeBean> webCodeMap = new HashMap<>();
        for (WebCodeBean webCodeBean : webCodeBeanList){
            WebCodeBean old = webCodeMap.get(webCodeBean.getApiUrl());
            if(old == null){
                webCodeMap.put(webCodeBean.getApiUrl(),webCodeBean);
            }else {
                //判断是否是最新的版本
                boolean latest = webCodeBean.latestVersion(old.getVersion());
                if(latest){
                    webCodeMap.put(webCodeBean.getApiUrl(),webCodeBean);
                }
            }
        }


        List<File> fileList = new ArrayList<>();
        for (Map.Entry<String,WebCodeBean> entry : webCodeMap.entrySet()){
            WebCodeBean webCodeBean = entry.getValue();
            String filePath = getCodeFilePath(webCodeBean);
            File file = new File(filePath);
            try {
                FileUtils.write(file,webCodeBean.getWebDslJson(),"utf-8");
            } catch (IOException e) {
                e.printStackTrace();
            }

            fileList.add(file);
        }
        FileOutputStream fos2 = null;
        try {
            String zipCodePath = getZipCodeFilePath(moduleBean);
            fos2 = new FileOutputStream(zipCodePath);
            ZipUtils.toZip(fileList, fos2);

            return zipCodePath;

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return "构建webCode zip包失败!";
    }

    /**
     * 获取构建的文件路径和文件名
     * @param webCodeBean
     * @return
     */
    private String getCodeFilePath(WebCodeBean webCodeBean){
        //写文件到项目目录中
        // 获取classpath
        String classpath = null;
        try {
            classpath = ResourceUtils.getURL("classpath:webcode").getPath();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        SecureRandom random = new SecureRandom();
        if(StringUtils.isEmpty(webCodeBean.getApiUrl())){
            return classpath + "/" + webCodeBean.getProjectCode() + "/" +webCodeBean.getModuleCode() + "/" + random.nextInt(100000) + "." + webCodeBean.getContentType();
        }else {
            return classpath + "/" + webCodeBean.getProjectCode() + "/" +webCodeBean.getModuleCode() + "/" +webCodeBean.getApiUrl().replace("/","").replace("?","")+
                    webCodeBean.getVersion()+"."  + webCodeBean.getContentType();
        }



    }

    /**
     * 获取压缩文件的路径
     * @param moduleBean
     * @return
     */
    private String getZipCodeFilePath(ModuleBean moduleBean){
        //写文件到项目目录中
        // 获取classpath
        String classpath = null;
        try {
            classpath = ResourceUtils.getURL("classpath:webcode").getPath();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        SecureRandom random = new SecureRandom();
        return classpath + "/" + moduleBean.getProjectCode() + "/" +moduleBean.getModuleCode() +random.nextInt(1000000000)+".zip";

    }

}
